﻿/* *************************************************************************
 * Copyright (c)2012 NTT DATA BEEN (China) Information Technology Co.,Ltd.
 * 作成者  ：gaoyunpeng
 * 機能概要：
 * 改訂履歴：
 * 2012/6/13 17:44:43 新規 gaoyunpeng
 * 2012/07/31 添加 Yunpeng.Gao 使通用宿主可以启动实现IHost接口的对象以及自定义入口点的对象
 * *************************************************************************/

 

namespace NTTDATA.BEENChina.ResultCertification.Host.Core
{
  
    using System.Collections.Generic; 
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.ServiceModel;
    using System.Threading.Tasks;

    public class Host : IHost
    {
        private static IHost _Instance = null;
        private static object _SyncRoot = new object();

        private static List<ServiceHost> _HostList;
        private static List<IHost> _OpenableModules;
        private static List<Task> _EntryModulesTaskList;
        private static HostCoreConfig _Config;

        /// <summary>
        /// 获取Host对象的唯一实例
        /// </summary>
        /// <returns></returns>
        public static IHost GetInstance(HostCoreConfig config)
        {
            if (null == _Instance)
            {
                lock (_SyncRoot)
                {
                    if (null == _Instance)
                    {
                        _Instance = new Host(config);
                    }
                }
            }
            return _Instance;
        }

        private Host(HostCoreConfig config)
        {
            _HostList = new List<ServiceHost>();
            _OpenableModules = new List<IHost>();
            _EntryModulesTaskList = new List<Task>();
            _Config = config;
        }

        #region IOpen 成员

        /// <summary>
        /// 打开WCF服务
        /// </summary>
        public void Open()
        {
            LoadServiceModules();
            foreach (ServiceHost host in _HostList)
            {
                host.Open();
            }
            foreach (IHost openableModule in _OpenableModules)
            {
                openableModule.Open();
            }
            foreach (Task task in _EntryModulesTaskList)
            {
                task.Start();
            }
        }

        private static void LoadServiceModules()
        {
            _HostList.Clear();
            _OpenableModules.Clear();
            _EntryModulesTaskList.Clear();
            //把所有属于同一程序集的对象放在一起
            IOrderedEnumerable<Module> modules = _Config.Modules.Cast<Module>().OrderBy(t => t.Name);
            Assembly moduleAssembly = Assembly.GetExecutingAssembly();
            string assemblyPath = Path.GetDirectoryName(moduleAssembly.Location);
            foreach (Module module in modules)
            {
                string moduleLocation = Path.Combine(assemblyPath, module.Name);
                if (File.Exists(moduleLocation))
                {
                    //避免重复生成程序集对象
                    if (0 != string.Compare(moduleAssembly.Location, moduleLocation))
                    {
                        moduleAssembly = Assembly.LoadFrom(moduleLocation);
                    }
                    object instance = moduleAssembly.CreateInstance(module.Type);
                    MethodInfo method;
                    if (!string.IsNullOrEmpty(module.EntryPoint) &&
                        null != (method = instance.GetType().GetMethod(module.EntryPoint)))
                    {
                        _EntryModulesTaskList.Add(new Task(() =>
                        {
                            method.Invoke(instance, null);
                        }));
                    }
                    else if (instance is IHost)
                    {
                        _OpenableModules.Add(instance as IHost);
                    }
                    else
                    {
                        //如果程序集内没有找到指定的类型，则instance为null
                        if (null != instance)
                        {
                            _HostList.Add(new ServiceHost(instance.GetType()));
                        }
                    }
                }
            }
        }

        public void Close()
        {
            foreach (ServiceHost host in _HostList)
            {
                host.Close();
            }
            foreach (IHost openableModule in _OpenableModules)
            {
                openableModule.Close();
            }
            foreach (Task task in _EntryModulesTaskList)
            {
                if ((task.Status & (TaskStatus.Canceled | TaskStatus.Faulted | TaskStatus.RanToCompletion)) == task.Status)
                {
                    task.Dispose();
                }
            }
        }

        #endregion

        #region IDisposable 成员

        public void Dispose()
        {
            try
            {
                Close();
            }
            catch { }
        }

        #endregion
    }
}
